package com.jule.teenpatti.game.vavle.notice;

import JoloProtobuf.GameSvr.JoloGame;
import com.google.common.primitives.Ints;
import com.jule.teenpatti.base.enums.TableStateEnum;
import com.jule.teenpatti.game.config.Config;
import com.jule.teenpatti.game.dao.bean.CommonConfigModel;
import com.jule.teenpatti.game.gameUtil.GameLogic;
import com.jule.teenpatti.game.model.PlayerInfo;
import com.jule.teenpatti.game.model.eenum.PlayTypeEnum;
import com.jule.teenpatti.game.model.eenum.PlayerStateEnum;
import com.jule.teenpatti.game.network.protocol.protoutil.TablePlayCurractionPlayerInfo;
import com.jule.teenpatti.game.play.AbstractTable;
import com.jule.teenpatti.game.play.TableUtil;
import com.jule.teenpatti.game.service.RobotStrategyService;
import com.jule.teenpatti.game.service.holder.CardOfTableHolder;
import com.jule.teenpatti.game.service.holder.FunctionIdHolder;
import com.jule.teenpatti.game.utils.log.TableLogUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.*;

/**
 * 广播通知处理类
 */
public class NoticeBroadcastMessages {

    private final static Logger logger = LoggerFactory.getLogger(NoticeBroadcastMessages.class);

    //TODO:新玩家入座 51001
    public static void playerSitDown(final AbstractTable table, String userId) {
        PlayerInfo player = table.getPlayer(userId);
        table.boardcastMessage(table.getTableId(),
                JoloGame.JoloGame_Notice2Client_SitDownReq.newBuilder()
                        .setUserId(player.getPlayerId())
                        .setRoomId(table.getRoomId())
                        .setTableId(table.getTableId())
                        .setNickName(player.getNickName())
                        .setPlayScore(player.getPlayScoreStore())
                        .setSeatNum(player.getSeatNum())
                        .setIcon(player.getIcon())
                        .build(),
                FunctionIdHolder.Game_Notice_SiteDown);
    }

    //TODO:玩家站起 51002
    public static void playerStandUp(final AbstractTable table, String userId, int seatNum) {
        logger.debug("player={},发送站起 time = {}" ,userId,String.valueOf(System.currentTimeMillis()));
        PlayerInfo player = null;
        try {
            player = table.getPlayer(userId);
            table.boardcastMessage(table.getTableId(),
                    JoloGame.JoloGame_Notice2Client_StandUpReq.newBuilder()
                            .setUserId(userId)
                            .setRoomId(table.getRoomId())
                            .setTableId(table.getTableId())
                            .setNickName(player != null ? player.getNickName() : "")
                            .setSeatNum(seatNum)
                            .setInGamePlayers(table.getInGamePlayers().size())
                            .build(),
                    FunctionIdHolder.Game_Notice_StandUp);
        } catch (Exception ex) {
            logger.error("发送玩家站起Notice失败，userId->{}, roomId->{}, tableId->{}, ex->{}",
                    userId, table.getRoomId(), table.getTableId(), ex.getMessage(), ex);
        }
        if (null != player) {
            player.resetGameingInfo();//清空玩家数据
        }
        logger.debug("player={},发送站起ok time = {}" ,userId,String.valueOf(System.currentTimeMillis()));
    }

    //TODO:强制玩家站起
//    public static void forcedStandUp(final Table table) {
//        DeskConfig desk = DeskConfigHolder.getInstance().getDeskConfig(table.getTableId());//获取桌子的所有基本信息
//        long minBet = desk.getMix_bet().longValue();//获取房间最小下注值
//        for (int in : table.getTableMap().keySet()) {
//            Player player = table.getTableMap().get(in);
//            if (player != null && (player.getPlayScoreStore() < minBet || player.getOperationInAdvance() == 1 || player.isOffLine())) { //如果玩家桌面货币小于最小下注
//                table.boardcastMessage(table.getTableId(), JoloGame.JoloGame_Notice2Client_StandUpReq.newBuilder()
//                        .setUserId(player.getPlayerId())
//                        .setNickName(player.getNickName())
//                        .setPlayScoreStore(player.getPlayScoreStore() + "")
//                        .setSeatNum(player.getPositionId())
//                        .build(), 51002);
//                if (!player.isOffLine()) {
//                    table.delPosition(player.getPositionId());
//                    long currentMoney = MoneyService.getInstance().updateMoney(player.getPlayerId(), player.getPlayScoreStore());
//                    player.setState(0); //修改玩家状态值为旁观
//                    RoomStateService.getInstance().onPlayerStandUp(table, player);//更新房间状态
//                } else {
//                    //离线
//                    table.delPosition(player.getPositionId());
//                    long currentMoney = MoneyService.getInstance().updateMoney(player.getPlayerId(), player.getPlayScoreStore());
//                    player.setState(0); //修改玩家状态值为旁观
//                    RoomStateService.getInstance().onPlayerStandUpAndLeave(table, player);
//                    table.removePlayers(player.getPlayerId());//todo 是否安全
//                    OperationCard.clearPlayer(player);//离桌后清空玩家数据
//
//                }
//            }
//            if (player.getIsBandar() != 0 && player.getOperationInAdvance() == 1) {  //庄家强制强制站起后更新庄家状态
//                table.setLocation(player.getPositionId());
//                player.setOperationInAdvance(0);
//                player.setIsBandar(0);
//            }
//        }
//    }


    //TODO:玩家买入筹码
    public static void buyIn(AbstractTable table, String userId, double buyInScore) {
        PlayerInfo player = table.getPlayer(userId);
        table.boardcastMessage(table.getTableId(), JoloGame.JoloGame_Notice2Client_BuyInReq.newBuilder()
                .setUserId(userId)
                .setRoomId(table.getRoomId())
                .setTableId(table.getTableId())
                .setNickName(player.getNickName())
                .setSeatNum(player.getSeatNum())
                .setBuyInScore(buyInScore)
                .setPlayScoreStore(player.getPlayScoreStore())
                .build(), FunctionIdHolder.Game_Notice_BuyIn);
    }

    //TODO：牌局开始 51004
    public static void gameStart(AbstractTable tableInfo) {
        JoloGame.JoloGame_Notice2Client_GameStartReq.Builder gameStart =
                JoloGame.JoloGame_Notice2Client_GameStartReq.newBuilder();
        gameStart.setRoomId(tableInfo.getRoomId())
                .setTableId(tableInfo.getTableId())
                .setGameOrderId(tableInfo.getCurrGameOrderId())
                .setCountDownSec(tableInfo.getCommonConfig().getGameStartCountDownSec());
        if (tableInfo.isPropertyChange()) {
            gameStart.setBootAmount(tableInfo.getRoomConfig().getAnte())
                    .setChaalLimit(tableInfo.getRoomConfig().getMaxBetScore())
                    .setMaxBlinds(tableInfo.getRoomConfig().getMaxBlindRound())
                    .setPotLimit(tableInfo.getRoomConfig().getMaxPot())
                    .setChangeResult(1);
        }
        tableInfo.boardcastMessage(tableInfo.getTableId(), gameStart.build(),
                FunctionIdHolder.Game_Notice_GameStart);
        TableLogUtil.gameStart(FunctionIdHolder.Game_Notice_GameStart, "gameStart",
                "" + tableInfo.getPlayType(), tableInfo.getRoomId(), tableInfo.getTableId(),
                tableInfo.getCurrGameOrderId(), TableUtil.inGamePlayersBySeatNumToString(tableInfo), tableInfo.getCurrDealerSeatNum(),
                TableUtil.tableInfoToString(tableInfo));
    }

    //TODO：通知全部客户端->发牌轮->开始 51005
    public static void giveCardRoundStart(AbstractTable table, PlayerInfo firstBetPlayer) {
        JoloGame.JoloGame_Notice2Client_GiveCardRound_StartReq.Builder reqBuilder = JoloGame.JoloGame_Notice2Client_GiveCardRound_StartReq.newBuilder();
        reqBuilder.setRoomId(table.getRoomId())
                .setTableId(table.getTableId())
                .setGameOrderId(table.getCurrGameOrderId())
                .addAllPlayerInfoList(TableUtil.getPlayers(table))
                .setBaseBetScore(table.getCurrBaseBetScore() / 2)
                .setBetRoundId(table.getCurrRoundId())
                .setNextActionPlayerInfo(getNextActionPlayerInfo(table,firstBetPlayer));
        table.boardcastMessage(table.getTableId(), reqBuilder.build(), FunctionIdHolder.Game_Notice_GiveCardRound_Start);
    }

    //TODO：通知全部客户端->癞子牌 51019
    public static void mixedCard(AbstractTable table) {
        JoloGame.JoloGame_Notice2Client_Mixed_CardReq.Builder mixed_cardReq = JoloGame.JoloGame_Notice2Client_Mixed_CardReq.newBuilder();
        mixed_cardReq.setRoomId(table.getRoomId());
        mixed_cardReq.setTableId(table.getTableId());
        mixed_cardReq.setGameOrderId(table.getCurrGameOrderId());
        int mixedCard = new Random().nextInt(13) + 1;
        table.setMixedCardId(mixedCard); //记录本局的癞子牌ID
        mixed_cardReq.setMixedCardId(mixedCard);
        table.boardcastMessage(table.getTableId(), mixed_cardReq.build(), FunctionIdHolder.Game_Notice2Client_Mixed_Card);
    }

    //TODO:通知全部客户端->下注轮次->玩家实施下注 51007
    public static void betRoundDoBet(AbstractTable table, int betSeqId, PlayerInfo doBetPlayer, PlayerInfo nextBetPlayer,boolean isBet) {
        logger.debug("下注：发送广播 time = {}" ,String.valueOf(System.currentTimeMillis()));
        JoloGame.JoloGame_Notice2Client_BetRound_DoBetReq.Builder reqBuilder = JoloGame.JoloGame_Notice2Client_BetRound_DoBetReq.newBuilder();
        reqBuilder.setRoomId(table.getRoomId())
                .setTableId(table.getTableId())
                .setGameOrderId(table.getCurrGameOrderId())
                .setBetUserId(doBetPlayer.getPlayerId())
                .setBetUserSeatNum(doBetPlayer.getSeatNum())
                .setBetScore(doBetPlayer.getAlreadyBetScore4Round())
                .setIsBlind(doBetPlayer.getIsBlind())
                .setBetRoundId(table.getCurrRoundId())
                .setTotalAlreadyBet(table.getTotalAlreadyBet())
                .setBetSeqId(betSeqId)
                .setIsBet(isBet);
        if (doBetPlayer.isSideshowOvertime()) {
            reqBuilder.setPlayerBetState(1);
            doBetPlayer.setSideshowOvertime(false);
        }
        JoloGame.JoloGame_TablePlay_NextActionPlayerInfo.Builder nextActionBuilder = getNextActionPlayerInfo(table,nextBetPlayer);
        if(nextActionBuilder != null){
            reqBuilder.setNextActionPlayerInfo(nextActionBuilder);
        }
        table.boardcastMessage(table.getTableId(),
                reqBuilder.build(),
                FunctionIdHolder.Game_Notice_BetRound_DoBet);
        logger.debug("下注：发送广播Success time = {}" ,String.valueOf(System.currentTimeMillis()));
    }

    //TODO:通知全部客户端->玩家已看牌 51008
    public static void playerSeeCard(AbstractTable table, PlayerInfo player, PlayerInfo playerInfo) {
        JoloGame.JoloGame_Notice2Client_PlayerSeeCardReq.Builder builder = JoloGame.JoloGame_Notice2Client_PlayerSeeCardReq.newBuilder();
        builder.setRoomId(table.getRoomId());
        builder.setTableId(table.getTableId());
        builder.setGameOrderId(table.getCurrGameOrderId());
        builder.setUserId(player.getPlayerId());
        builder.setSeatNum(player.getSeatNum());//todo 此处要加上一个值 用来更新sideshow的状态
        if (playerInfo != null) {
            builder.setCurrActionPlayerId(playerInfo.getPlayerId());
            builder.setIsCanShow((table.getInGamePlayers().size() == 2 && table.getCurrRoundId() > 1) ? 1 : 0);
            builder.setIsCanSideShow((table.getInGamePlayers().size() > 2 && table.getCurrRoundId() > 1) ? 1 : 0);
            CommonConfigModel config = table.getCommonConfig();
            if (playerInfo.getIsBlind() == 1) {
                builder.setBetScore(table.getCurrBaseBetScore() / 2);
            } else {
                builder.setBetScore(table.getCurrBaseBetScore());
            }
//            //如果当前sideshow不需要对方同意，则比牌时双倍下注
//            if (!config.isNeedAllowSideShow() && playerInfo.getIsCanSideShow() == 1) {
//                builder.setIsNeedAllowSideShow(1);
//            }
        }
        table.boardcastMessage(table.getTableId(),
                builder.build(),
                FunctionIdHolder.Game_Notice_PlayerSeeCard);
    }


    //TODO:通知全部客户端->SideShow->玩家申请比牌 51009
    public static void applySideShow(AbstractTable table, PlayerInfo player, PlayerInfo targetPlayer) {
        JoloGame.JoloGame_Notice2Client_SideShow_ApplySideShowReq.Builder reqBuilder = JoloGame.JoloGame_Notice2Client_SideShow_ApplySideShowReq.newBuilder();
        reqBuilder.setRoomId(table.getRoomId())
                .setTableId(table.getTableId())
                .setGameOrderId(table.getCurrGameOrderId())
                .setSideShowUserId(player.getPlayerId())
                .setSideShowUserSeatNum(player.getSeatNum())
                .setSideShowBetScore(player.getAlreadyBetScore4Round())
                .setTargetUserId(targetPlayer.getPlayerId())
                .setTargetUserSeatNum(targetPlayer.getSeatNum());
        table.boardcastMessage(table.getTableId(),
                reqBuilder.build(),
                FunctionIdHolder.Game_Notice_SideShow_ApplySideShow);
    }


    //TODO:通知全部客户端->SideShow->等待目标玩家同意比牌申请 51010
    public static void sideShowWaitTargetUserAllow(AbstractTable table, String userId) {
        table.boardcastMessage(table.getTableId(),
                JoloGame.JoloGame_Notice2Client_SideShow_WaitTargetUserAllowReq.newBuilder()
                        .setRoomId(table.getRoomId())
                        .setTableId(table.getTableId())
                        .setGameOrderId(table.getCurrGameOrderId())
                        .setUserId(userId)
                        .setCountDownSec(table.getCommonConfig().getAllowSideShowCountDownSec())
                        .build(), FunctionIdHolder.Game_Notice_SideShow_WaitTargetUserAllow);
    }

    //TODO:通知全部客户端->sideShow->等待玩家选择指定的用户 51011
    public static void sideShowWaitChooseUser(AbstractTable table, PlayerInfo player) {
        table.boardcastMessage(table.getTableId(),
                JoloGame.JoloGame_Notice2Client_SideShow_WaitChooseUserReq.newBuilder()
                        .setRoomId(table.getRoomId())
                        .setTableId(table.getTableId())
                        .setGameOrderId(table.getCurrGameOrderId())
                        .setUserId(player.getPlayerId())
                        .setSeatNum(player.getSeatNum())
                        .setCountDownSec(table.getCommonConfig().getAllowSideShowCountDownSec())
                        .build(),
                FunctionIdHolder.Game_Notice_SideShow_WaitChooseUser);
    }

    //TODO:通知全部客户端->显示SideShow比牌结果 51012
    public static void sideShowResult(AbstractTable table, PlayerInfo winPlayer, PlayerInfo losePlayer, PlayerInfo nextBetPlayer) {
        JoloGame.JoloGame_Notice2Client_SideShow_SideShowResultReq.Builder reqBuilder = JoloGame.JoloGame_Notice2Client_SideShow_SideShowResultReq.newBuilder();
        reqBuilder.setRoomId(table.getRoomId())
                .setTableId(table.getTableId())
                .setGameOrderId(table.getCurrGameOrderId())
                .setWinPlayerUserId(winPlayer != null ? winPlayer.getPlayerId() : "")
                .setWinPlayerSeatNum(winPlayer != null ? winPlayer.getSeatNum() : 0)
                .setLosePlayerUserId(losePlayer != null ? losePlayer.getPlayerId() : "")
                .setLosePlayerSeatNum(losePlayer != null ? losePlayer.getSeatNum() : 0);
        JoloGame.JoloGame_TablePlay_NextActionPlayerInfo.Builder nextActionBuilder = getNextActionPlayerInfo(table,nextBetPlayer);
        if(nextActionBuilder != null){
            reqBuilder.setNextActionPlayerInfo(nextActionBuilder);
        }
        table.boardcastMessage(table.getTableId(),
                reqBuilder.build(),
                FunctionIdHolder.Game_Notice_SideShow_SideShowResult);
    }

    //TODO:通知全部客户端->通知结算结果 51013
    public static void settleResult(AbstractTable table, double winScore) {
        StringBuilder players = new StringBuilder();
        players.append("[");
        JoloGame.JoloGame_Notice2Client_SettleRound_SettleReq.Builder reqBuilder = JoloGame.JoloGame_Notice2Client_SettleRound_SettleReq.newBuilder();
        reqBuilder.setRoomId(table.getRoomId())
                .setTableId(table.getTableId())
                .setGameOrderId(table.getCurrGameOrderId());
        //赋值 结算信息列表
        List<JoloGame.JoloGame_TablePlay_PlayerSettleInfo> list = new ArrayList<>();
        for (PlayerInfo player : table.getInGamePlayersBySeatNum().values()) {
            if (player.getState() != PlayerStateEnum.fold && player.getState() != PlayerStateEnum.siteDown) {
//            if(player.getState() != PlayerStateEnum.siteDown){
                JoloGame.JoloGame_TablePlay_PlayerSettleInfo.Builder settltPlayerBuilder = JoloGame.JoloGame_TablePlay_PlayerSettleInfo.newBuilder();
                settltPlayerBuilder.setUserId(player.getPlayerId());
                settltPlayerBuilder.setSeatNum(player.getSeatNum());
                players.append("{seat:" + player.getSeatNum() + ",");
                players.append("userId:" + player.getPlayerId() + ",");
                players.append("nickName:" + player.getNickName() + ",");
                if (player.isWinner()) {
                    players.append("winLoseScore:" + winScore + "},");
                    settltPlayerBuilder.setWinLoseScore(winScore+player.getTotalAlreadyBetScore4Hand());
                    settltPlayerBuilder.setScore(winScore);
                } else {
                    players.append("winLoseScore:0},");
                    settltPlayerBuilder.setWinLoseScore(0);
                }
                settltPlayerBuilder.setPlayScoreStore(player.getPlayScoreStore());
                if (player.getIsBlind() == 1 && player.getHandCards() == null && table.currPlayType() != PlayTypeEnum.blind.getGameId() && table.getInGamePlayers().size() != 1) {
                    player.setHandCards(CardOfTableHolder.TakeCardOperationObj(table.getCurrGameOrderId()).hair_card(table.giveCardCounts(), player.getPlayerId()));
                }
                player.getHandCardTypeModel(table);

                if (null != player.getHandCards()) {
                    settltPlayerBuilder.addAllHandCards(Ints.asList(player.getHandCards()));
                }
                settltPlayerBuilder.addAllMixedCards(player.getMixedCardList() == null ? new ArrayList<>() : player.getMixedCardList());
                list.add(settltPlayerBuilder.build());
            }
            if (player.isWinner()){
                RobotStrategyService.OBJ.addRobotPool(player, winScore, true);
            }else {
                RobotStrategyService.OBJ.addRobotPool(player, player.getTotalAlreadyBetScore4Hand(), false);
            }
        }
        table.boardcastMessage(table.getTableId(),
                reqBuilder.addAllSettleInfoList(list).build(), FunctionIdHolder.Game_Notice_SettleRound_SettleResult);
        if (players.indexOf(",") > 0) {
            players.replace(players.length() - 1, players.length(), "");
        }
        players.append("]");
        TableLogUtil.settle(FunctionIdHolder.Game_Notice_SettleRound_SettleResult, "settleResult", table.getPlayType() + "",
                table.getRoomId(), table.getTableId(), players.toString());
    }

    //TODO:通知全部客户端->结算历史记录   51014
    public static void settleHistory(AbstractTable table) {
        JoloGame.JoloGame_Notice2Client_SettleRound_HistoryReq.Builder reqBuilder = JoloGame.JoloGame_Notice2Client_SettleRound_HistoryReq.newBuilder();
        reqBuilder.setRoomId(table.getRoomId())
                .setTableId(table.getTableId())
                .setGameOrderId(table.getCurrGameOrderId());

        //TODO：赋值 历史列表
        table.boardcastMessage(table.getTableId(),
                reqBuilder.build(),
                FunctionIdHolder.Game_Notice_SettleRound_History);
    }

    //TODO:通知全部客户端->sideShow->用户选择完成了被比牌用户 51015
    public static void sideShowCompleteChooseUser(AbstractTable table, PlayerInfo applyPlayer, PlayerInfo targetPlayer) {
        JoloGame.JoloGame_Notice2Client_SideShow_CompleteChooseUserReq.Builder reqBuilder = JoloGame.JoloGame_Notice2Client_SideShow_CompleteChooseUserReq.newBuilder();
        reqBuilder.setRoomId(table.getRoomId())
                .setTableId(table.getTableId())
                .setGameOrderId(table.getCurrGameOrderId())
                .setApplyUserId(applyPlayer.getPlayerId())
                .setApplyUserSeatNum(applyPlayer.getSeatNum())
                .setTargetUserId(targetPlayer.getPlayerId())
                .setTargetUserSeatNum(targetPlayer.getSeatNum());
        //TODO：赋值 历史列表
        table.boardcastMessage(table.getTableId(),
                reqBuilder.build(),
                FunctionIdHolder.Game_Notice_SideShow_CompleteChooseUser);
    }

    //TODO:通知全部客户端->sideShow->用户完成了是否允许比牌的选择 51016
    public static void sideShowCompleteAllow(AbstractTable table, PlayerInfo applyPlayer, PlayerInfo targetPlayer, int isAllow, PlayerInfo nextBetPlayer) {
        JoloGame.JoloGame_Notice2Client_SideShow_CompleteAllowReq.Builder reqBuilder = JoloGame.JoloGame_Notice2Client_SideShow_CompleteAllowReq.newBuilder();
        reqBuilder.setRoomId(table.getRoomId())
                .setTableId(table.getTableId())
                .setGameOrderId(table.getCurrGameOrderId())
                .setApplyUserId(applyPlayer.getPlayerId())
                .setApplyUserSeatNum(applyPlayer.getSeatNum())
                .setTargetUserId(targetPlayer.getPlayerId())
                .setTargetUserSeatNum(targetPlayer.getSeatNum())
                .setTargetUserIsAllow(isAllow);
        JoloGame.JoloGame_TablePlay_NextActionPlayerInfo.Builder nextActionBuilder = getNextActionPlayerInfo(table,nextBetPlayer);
        if(nextActionBuilder != null){
            reqBuilder.setNextActionPlayerInfo(nextActionBuilder);
        }
        table.boardcastMessage(table.getTableId(),
                reqBuilder.build(),
                FunctionIdHolder.Game_Notice_SideShow_CompleteAllow);
    }

    private static JoloGame.JoloGame_Notice2Client_Side_ShowReq.Builder messageBodyFill(AbstractTable table, PlayerInfo applyPlayer, PlayerInfo targetPlayer){
        JoloGame.JoloGame_Notice2Client_Side_ShowReq.Builder reqBuilder = JoloGame.JoloGame_Notice2Client_Side_ShowReq.newBuilder();
        reqBuilder.setRoomId(table.getRoomId())
                .setTableId(table.getTableId())
                .setApplyUserId(applyPlayer.getPlayerId())
                .setApplyUserSeatNum(applyPlayer.getSeatNum())
                .addAllApplyUserHandCards(new ArrayList(Ints.asList(applyPlayer.getHandCards())))
                .addAllApplyUserMixedCards(applyPlayer.getMixedCardList() == null ? new ArrayList<>() : applyPlayer.getMixedCardList())
                .setTargetUserId(targetPlayer.getPlayerId())
                .setTargetUserSeatNum(targetPlayer.getSeatNum())
                .addAllTargetUserHandCards(new ArrayList(Ints.asList(targetPlayer.getHandCards())))
                .addAllTargetUserMixedCards(targetPlayer.getMixedCardList() == null ? new ArrayList<>() : targetPlayer.getMixedCardList());
        return reqBuilder;
    }

    //sideshow比牌通知双方   51020
    public static void sideShowBothSides(AbstractTable table,String winner, PlayerInfo applyPlayer, PlayerInfo targetPlayer) {
        JoloGame.JoloGame_Notice2Client_Side_ShowReq.Builder reqBuilder = JoloGame.JoloGame_Notice2Client_Side_ShowReq.newBuilder();
        reqBuilder.setRoomId(table.getRoomId())
                .setTableId(table.getTableId())
                .setApplyUserId(applyPlayer.getPlayerId())
                .setApplyUserSeatNum(applyPlayer.getSeatNum())
                .addAllApplyUserMixedCards(applyPlayer.getMixedCardList() == null ? new ArrayList<>() : applyPlayer.getMixedCardList())
                .setTargetUserId(targetPlayer.getPlayerId())
                .setTargetUserSeatNum(targetPlayer.getSeatNum())
                .addAllTargetUserHandCards(new ArrayList())
                .addAllTargetUserMixedCards(targetPlayer.getMixedCardList() == null ? new ArrayList<>() : targetPlayer.getMixedCardList());
//        if(applyPlayer.getPlayerId().equals(winner) && applyPlayer.getHandCards() != null){
        if(applyPlayer.getPlayerId().equals(winner) && applyPlayer.getIsBlind() == 1){
            reqBuilder.addAllApplyUserHandCards(new ArrayList());
        }else{
            reqBuilder.addAllApplyUserHandCards(new ArrayList(Ints.asList(applyPlayer.getHandCards())));
        }
        NoticeRPCUtil.sendSingMsg(table.getPlayType(),applyPlayer.getPlayerId(),FunctionIdHolder.Game_Notice2Client_Side_Show,reqBuilder.build());
//        table.boardcastMessage(table.getTableId(), applyPlayer.getPlayerId(), targetPlayer.getPlayerId(),
//                messageBodyFill(table,applyPlayer,targetPlayer).build(),
//                FunctionIdHolder.Game_Notice2Client_Side_Show);
    }

    //轮数上限比牌通知全体   51028 todo
    public static void takeTurnsShow(AbstractTable table, PlayerInfo applyPlayer, PlayerInfo targetPlayer) {
        table.boardcastMessage(table.getTableId(),
                messageBodyFill(table,applyPlayer,targetPlayer).build(),
                FunctionIdHolder.Game_Notice2Client_Take_Turns_Show);
    }

    //孤注一掷比牌通知发起者   51029 todo
    public static void fullPressureShow(AbstractTable table,String userId) {
        table.boardcastMessage(table.getTableId(),
                JoloGame.JoloGame_Notice2Client_FullPressureShowReq.newBuilder()
                        .setRoomId(table.getRoomId())
                        .setTableId(table.getTableId())
                        .setUserId(userId).build(),
                FunctionIdHolder.Game_Notice2Client_FullPressureShow);
    }

    //TODO:通知全部客户端->betRound->用户弃牌 51017
    public static void applyFold(AbstractTable table, PlayerInfo applyPlayer, PlayerInfo nextBetPlayer) {
        logger.debug("弃牌：发送广播 time = {}" ,String.valueOf(System.currentTimeMillis()));
        if (applyPlayer != null) {
            //在弃牌时更新输赢
            applyPlayer.setChipsWon(0);
            applyPlayer.getHandsWon().add(0);
            applyPlayer.setChipsLost(applyPlayer.getCurChipsLose());
        }
        JoloGame.JoloGame_Notice2Client_BetRound_FoldReq.Builder reqBuilder = JoloGame.JoloGame_Notice2Client_BetRound_FoldReq.newBuilder();
        reqBuilder.setRoomId(table.getRoomId())
                .setTableId(table.getTableId())
                .setApplyUserId(applyPlayer == null ? table.getOfflinePlayerId() : applyPlayer.getPlayerId())
                .setApplyUserSeatNum(applyPlayer == null ? table.getOfflineSeatNum() : applyPlayer.getSeatNum())
                .setInGamePlayers(table.getInGamePlayers().size());
        if (table.getCurrGameOrderId() == null) {
            reqBuilder.setGameOrderId("");
        } else {
            reqBuilder.setGameOrderId(table.getCurrGameOrderId());
        }
        reqBuilder.setInGamePlayers(table.getInGamePlayers().size());
        JoloGame.JoloGame_TablePlay_NextActionPlayerInfo.Builder nextActionBuilder = getNextActionPlayerInfo(table,nextBetPlayer);
        if(nextActionBuilder != null){
            reqBuilder.setNextActionPlayerInfo(nextActionBuilder);
        }
        table.boardcastMessage(table.getTableId(),
                reqBuilder.build(),
                FunctionIdHolder.Game_Notice_BetRound_Fold);
        logger.debug("弃牌：发送广播 Success. time = {}" ,String.valueOf(System.currentTimeMillis()));
    }

    // 50015
    public static void currActionPlayerInfo(PlayerInfo player, AbstractTable table) {
        player.setIsCanShow((table.getInGamePlayers().size() == 2 && table.getCurrRoundId() > 1) ? 1 : 0);
        player.setIsCanSideShow((table.getInGamePlayers().size() > 2 && table.getCurrRoundId() > 1) ? 1 : 0);
        table.boardcastMessage(table.getTableId(),
                TablePlayCurractionPlayerInfo.fillCurrActionPlayerInfoAck(player, table)
                , FunctionIdHolder.Game_REQ_CurrActionPlayerInfo);
    }

    //异步：超过桌子盲牌轮次上线全体看牌或者超过桌子限制的总分后提醒玩家进入结算 51018
    public static void settlePrompt(AbstractTable table) {
        JoloGame.JoloGame_Notice2Client_Settle_PromptReq.Builder builder = JoloGame.JoloGame_Notice2Client_Settle_PromptReq.newBuilder();
        builder.setRoomId(table.getRoomId())
                .setTableId(table.getTableId())
                .setGameOrderId(table.getCurrGameOrderId())
                .setIsMaxBlindRound(0);
//        if (table.getTotalAlreadyBet() >= table.getMaxPotScore()) {
//            builder.setIsMaxBlindRound(0);
//        } else if (table.getCurrRoundId() == table.getRoomConfig().getMaxBlindRound() + 1) {
//            builder.setIsMaxBlindRound(1);
//        }
        table.boardcastMessage(table.getTableId(),
                builder.build(),
                FunctionIdHolder.Game_Notice2Client_Settle_Prompt);
    }

    //异步：玩家换牌广播 51021
    public static void changeCard(AbstractTable table, PlayerInfo player, int cardId, int tips) {
        table.boardcastMessage(table.getTableId(),
                JoloGame.JoloGame_Notice2Client_ChangeCardReq.newBuilder()
                        .setRoomId(table.getRoomId())
                        .setTableId(table.getTableId())
                        .setUserId(player.getPlayerId())
                        .setUserSeatNum(player.getSeatNum())
                        .setChangeCardScore(tips) //todo
                        .setTotalAlreadyBet(table.getTotalAlreadyBet()) //todo
                        .setChangeCard(cardId).build(),
                FunctionIdHolder.Game_Notice2Client_ChangeCard);
    }

    //异步：show比牌双方id 51022
    public static void bothSides(AbstractTable table, List<String> list) {
        try {
            PlayerInfo playerA = table.getPlayer(list.get(0));
            PlayerInfo playerB = table.getPlayer(list.get(1));
            PlayerInfo winner = null;
            if (playerA != null && playerB != null) {
                if (playerA.getIsBlind() == 1) {
                    //根据玩法的不同获取不同数量的手牌
                    int[] arrHandCards = CardOfTableHolder.TakeCardOperationObj(table.getCurrGameOrderId()).hair_card(table.giveCardCounts(), playerA.getPlayerId());
                    playerA.setHandCards(arrHandCards); //玩家看牌后则为手牌赋值
                }
                if (playerB.getIsBlind() == 1) {
                    //根据玩法的不同获取不同数量的手牌
                    int[] arrHandCards = CardOfTableHolder.TakeCardOperationObj(table.getCurrGameOrderId()).hair_card(table.giveCardCounts(), playerB.getPlayerId());
                    playerB.setHandCards(arrHandCards); //玩家看牌后则为手牌赋值
                }
                //广播事件：通知全部客户端，用户已经完成了是否同意比牌的操作
                playerA.getHandCardTypeModel(table);
                playerB.getHandCardTypeModel(table);
                winner = table.getWinnerByCompareCards(playerA, playerB);
            }
            table.boardcastMessage(table.getTableId(),
                    JoloGame.JoloGame_Notice2Client_both_sidesReq.newBuilder()
                            .addAllPlayers(list)
                            .setPlayerId(winner.getPlayerId().equals(playerA.getPlayerId()) ? playerB.getPlayerId() : playerA.getPlayerId()).build(),
                    FunctionIdHolder.Game_Notice2Client_bothSides);
//            GameLogic.SideShowResultCD(table, playerA, playerB, winner);
            //设置桌子状态为比牌中
            table.setTableStateEnum(TableStateEnum.OPEN_CARD);
            //调用定时器来延迟结算时间
            GameLogic.commonTimer(table, 4, false);
        }catch (Exception e){
            logger.error(e.getMessage());
        }
    }

    //异步：show比牌双方id 51024
    public static void bothSideshows(AbstractTable table, List<String> list) {
        try {
            PlayerInfo playerA = table.getPlayer(list.get(0));
            PlayerInfo playerB = table.getPlayer(list.get(1));
            PlayerInfo winner = null;
            if (playerA != null && playerB != null) {
                winner = GameLogic.getSideShowResult(table, playerA, playerB);
            }
            table.boardcastMessage(table.getTableId(),
                    JoloGame.JoloGame_Notice2Client_both_sidesReq.newBuilder()
                            .addAllPlayers(list)
                            .setPlayerId(winner.getPlayerId().equals(playerA.getPlayerId()) ? playerB.getPlayerId() : playerA.getPlayerId()).build(),
                    FunctionIdHolder.Game_Notice2Client_bothSideshows);
            //设置桌子状态为比牌中
            table.setTableStateEnum(TableStateEnum.OPEN_CARD);
            GameLogic.SideShowResultCD(table, playerA, playerB, winner);
        }catch (Exception e){
            logger.error(e.getMessage());
        }
    }

    //异步：show比牌双方 只用与房间轮次达到顶峰
    public static void takeTurnsShow(AbstractTable table, List<String> list) {
        try {
            PlayerInfo playerA = table.getPlayer(list.get(0));
            PlayerInfo playerB = table.getPlayer(list.get(1));
            PlayerInfo winner = null;
            if (playerA != null && playerB != null) {
                winner = GameLogic.getSideShowResult(table, playerA, playerB);
            }
            table.boardcastMessage(table.getTableId(),
                    JoloGame.JoloGame_Notice2Client_both_sidesReq.newBuilder()
                            .addAllPlayers(list)
                            .setPlayerId(winner.getPlayerId().equals(playerA.getPlayerId()) ? playerB.getPlayerId() : playerA.getPlayerId()).build(),
                    FunctionIdHolder.Game_Notice2Client_bothSideshows);
            if (table.getInGamePlayers().size() > 1) {
                GameLogic.takeTurnsShowCD(table, playerA, playerB,winner);
            } else {
                GameLogic.commonTimer(table, 4, false);
            }
        }catch (Exception e){
            e.printStackTrace();
            logger.error(e.getMessage());
        }
    }

    //异步：用户选择玩法广播          51025
    public static void choosePlayTypes(AbstractTable table) {
        JoloGame.JoloGame_Notice2Client_Choose_PlayTypeReq.Builder builder = JoloGame.JoloGame_Notice2Client_Choose_PlayTypeReq.newBuilder();
        builder.setRoomId(table.getRoomId())
                .setTableId(table.getTableId())
                .setGameOrderId(table.getCurrGameOrderId())
                .setChoosePlayTypeCd(Config.CHOOSE_PLAYTYPE_CD);
        for (PlayerInfo player : table.getInGamePlayers().values()) {
            if (player.getSeatNum() == table.getCurrDealerSeatNum()) {
                builder.addAllPlayType(PlayTypeEnum.getPlayTypes())
                        .setDealerId(player.getPlayerId());
            } else {
                builder.addAllPlayType(new ArrayList<>());
            }
        }

        table.boardcastMessage(table.getTableId(), builder.build(), FunctionIdHolder.Game_Notice2Client_ChoosePlayType);
    }

    //异步：当前选定的玩法广播            51026

    /**
     *
     * @param table
     * @param none 没有人选择玩法
     */
    public static void selectedPlayType(AbstractTable table, boolean none) {
        String dealerId = "";

        if (table.getCurrDealerSeatNum() > 0) {
            if (table.getInGamePlayersBySeatNum().containsKey(table.getCurrDealerSeatNum())) {
                dealerId = table.getInGamePlayersBySeatNum().get(table.getCurrDealerSeatNum()).getPlayerId();
            }
        }
        table.boardcastMessage(table.getTableId(), JoloGame.JoloGame_Notice2Client_PlayTypeReq.newBuilder()
                .setRoomId(table.getRoomId())
                .setTableId(table.getTableId())
                .setGameOrderId(table.getCurrGameOrderId())
                .setPlayType(table.getDealerPlayType() + "")
                .setDealerId(none ? "" : dealerId
                )
                .build(), FunctionIdHolder.Game_Notice2Client_SelectedPlayType);
    }

    //赠送礼物
    public static void giveGifts(AbstractTable tableInfo, String userId, int isSendToAll, String itemId, Collection<String> targetIds) {
        JoloGame.JoloGame_Notice2Client_GiveGiftsReq.Builder notice = JoloGame.JoloGame_Notice2Client_GiveGiftsReq.newBuilder();
        notice.setUserId(userId)
                .setRoomId(tableInfo.getRoomId())
                .setTableId(tableInfo.getTableId())
                .setIsSendToAll(isSendToAll)
                .setItemId(itemId)
                .addAllTargetIds(targetIds);
        tableInfo.boardcastMessage(tableInfo.getTableId(), notice.build(), FunctionIdHolder.Game_Notice_GiveGift);
    }

    //打赏荷官
    public static void rewardCroupier(AbstractTable tableInfo, String userId) {
        JoloGame.JoloGame_Notice2Client_RewardCroupierReq.Builder notice = JoloGame.JoloGame_Notice2Client_RewardCroupierReq.newBuilder();
        notice.setRoomId(tableInfo.getRoomId())
                .setTableId(tableInfo.getTableId())
                .setUserId(userId)
                .setTipValue(tableInfo.getRoomConfig().getTipValue());

        tableInfo.boardcastMessage(tableInfo.getTableId(), notice.build(), FunctionIdHolder.Game_Notice_RewardCroupier);
    }

    //51027 玩家准备广播
    public static void gamePrepare(AbstractTable tableInfo,PlayerInfo player){
        tableInfo.boardcastMessage(tableInfo.getTableId(),
                JoloGame.JoloGame_Notice2Client_GamePrepareReq.newBuilder()
                .setRoomId(player.getRoomId())
                .setTableId(player.getTableId())
                .setUserId(player.getPlayerId())
                .setSeatNum(player.getSeatNum()).build(),
                FunctionIdHolder.Game_Notice2Client_GamePrepare);
    }

    //51030 喜钱广播
    public static void xiQian(AbstractTable tableInfo,PlayerInfo player,double score){
        tableInfo.boardcastMessage(tableInfo.getTableId(),
                JoloGame.JoloGame_Notice2Client_XiQianReq.newBuilder()
                        .setRoomId(player.getRoomId())
                        .setTableId(player.getTableId())
                        .setScore(score) //此处没有配置 暂时写固定值
                        .setUserIds(player.getPlayerId())
                        .setSeatNum(player.getSeatNum()).build(),
                FunctionIdHolder.Game_Notice2Client_XiQian);
    }

    /**
     * 发送筹码变化通知
     * @param table
     * @param uid
     * @param money
     */
    public static void moneyChangeNotice(AbstractTable table, String uid, double money){
        /*
         * 注释By gx 20181024 既然已经将排除自己的代码注释掉，那么将发送广播修改为牌桌群发，避免执行无意义的for循环，浪费cpu
         */
//        //排除自己
//        List<String> list = new ArrayList<>();
//        table.getAllPlayers().forEach( (k,v) -> {
////            if (!k.equals(uid)){
//                list.add(v.getPlayerId());
////            }
//        } );
//
//        //发送广播
//        table.boardcastMuliMessage(
//                table.getTableId(),
//                list,
//                JoloGame.JoloGame_NoticeCurMoney.newBuilder().setRoomId(table.getRoomId()).setTableId(table.getTableId()).setGameOrderId(table.getCurrGameOrderId()).setUserId(uid).setCurMoney(money).build(),
//                FunctionIdHolder.Game_NoticeCurMoney);


        table.boardcastMessage(table.getTableId(),
                JoloGame.JoloGame_NoticeCurMoney.newBuilder()
                        .setRoomId(table.getRoomId())
                        .setTableId(table.getTableId())
                        .setGameOrderId(table.getCurrGameOrderId())
                        .setUserId(uid).setCurMoney(money).build(),
                FunctionIdHolder.Game_NoticeCurMoney);
    }

    public static JoloGame.JoloGame_TablePlay_NextActionPlayerInfo.Builder getNextActionPlayerInfo(AbstractTable table, PlayerInfo nextBetPlayer){
        //可选项：下一个行动的玩家信息
        if (null != nextBetPlayer) {
            JoloGame.JoloGame_TablePlay_NextActionPlayerInfo.Builder nextActionBuilder = JoloGame.JoloGame_TablePlay_NextActionPlayerInfo.newBuilder();
            nextActionBuilder.setNextBetUserId(nextBetPlayer.getPlayerId())
                    .setNextBetUserSeatNum(nextBetPlayer.getSeatNum())
                    .setNextBetIsCanSideShow((table.getInGamePlayers().size() > 2 && table.getCurrRoundId() > 1) ? 1 : 0)
                    .setNextBetIsCanShow((table.getInGamePlayers().size() == 2 && table.getCurrRoundId() > 1) ? 1 : 0)
                    .setBetRoundId(table.getCurrRoundId())
                    .setNextBetCountDownSec(table.getCommonConfig().getBetCountDownSec());
            if (nextBetPlayer.getIsBlind() == 1) {
                nextActionBuilder.setNextBetBaseBetScore(table.getCurrBaseBetScore() / 2);
            } else {
                nextActionBuilder.setNextBetBaseBetScore(table.getCurrBaseBetScore());
            }
            nextActionBuilder.setCurrMultiple((int)(table.getCurrBaseBetScore() / 2 / table.getRoomConfig().getAnte()));
            return nextActionBuilder;
        }
        return null;
    }
}
